/*
 *
 * Copyright ShangHai ECLUB Information Technology Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.eclub.emotion.rootstone.server.core;

import org.apache.log4j.Logger;

import com.eclub.emotion.rootstone.protocol.Protocol;
import com.eclub.emotion.rootstone.protocol.sdp.RequestProtocol;
import com.eclub.emotion.rootstone.protocol.sdp.ResponseProtocol;
import com.eclub.emotion.rootstone.protocol.util.KeyValuePair;
import com.eclub.emotion.rootstone.server.context.Global;
import com.eclub.emotion.rootstone.server.context.IProxyStub;
import com.eclub.emotion.rootstone.server.context.Response;
import com.eclub.emotion.rootstone.server.context.RsContext;
import com.eclub.emotion.rootstone.server.context.StopWatch;
import com.eclub.emotion.rootstone.server.http.mapping.ServiceMethodHandler;


public abstract class AbstractInvocationHandler implements InvocationHandler{
	private Logger LOGGER = Logger.getLogger(getClass());
	
	
	public abstract void doInvoke(RsContext context);
	
	public void invoke(RsContext context){
		StringBuffer sb = new StringBuffer();
		StopWatch sw = context.getStopWatch();
		Object response = null;
		Protocol protocol = null;
		
		try {
		    protocol = context.getProtocol();
			RequestProtocol request = (RequestProtocol)protocol.getSdpEntity();
			
			sb.append("protocol version:").append(protocol.getVersion());
			sb.append("\nfromIP:").append(context.getChannel().getRemoteIP());
			LOGGER.debug(sb.toString());
			
			ServiceMethodHandler serviceMethodHandler  = context.getHttpResuest().getServiceMethodHandler();
			IProxyStub localProxy = Global.getSingleton().getProxyFactory().getProxy(serviceMethodHandler.getHandlerMethodName());
			LOGGER.debug("proxyFactory.getProxy finish");

			if (localProxy == null) {
				throw new RuntimeException("Service not found");
			} else {
				LOGGER.debug("begin localProxy.invoke");
				String swInvoderKey = "InvokeRealService_" +serviceMethodHandler.getHandlerMethodName()+ "." + request.getMethodName();
				sw.startNew(swInvoderKey, sb.toString());
				sw.setFromIP(context.getChannel().getRemoteIP());
				sw.setLocalIP(context.getChannel().getLocalIP());
				
				//invoker real service
				Response res = localProxy.invoke(context);
				
				sw.stop(swInvoderKey);
				
				LOGGER.debug("end localProxy.invoke");
				context.setGaeaResponse(res);
				response = createResponse(res);
				LOGGER.debug("localProxy.invoke finish");
			}
		} catch (RuntimeException sfe) {
			context.setError(sfe);
		} catch (Throwable e) {
			LOGGER.error("Exception when invoke service fromIP:" + context.getChannel().getRemoteIP() + "  toIP:" + context.getChannel().getLocalIP(), e);
			context.setError(e);
		}
		
		protocol.setSdpEntity(response);
		
		doInvoke(context);
		
	}
	
	ResponseProtocol createResponse(Response gaeaResponse) {
		if(gaeaResponse.getOutParaList()!= null && gaeaResponse.getOutParaList().size() > 0){
			int outParaSize = gaeaResponse.getOutParaList().size();
			Object[] objArray = new Object[outParaSize];
			for(int i=0; i<outParaSize; i++) {
				objArray[i] = gaeaResponse.getOutParaList().get(i).getOutPara();
			}
            return new ResponseProtocol(gaeaResponse.getReturnValue(), objArray);
        } else {
            return new ResponseProtocol(gaeaResponse.getReturnValue(), null);
        }
	}
	
}


